using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Security.Claims;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Interfaces;

namespace UniversalAdmin.Api.Filters;

public class AuditLogActionFilter : IAsyncActionFilter
{
  private readonly IUnitOfWork _uow;

  public AuditLogActionFilter(IUnitOfWork uow)
  {
    _uow = uow;
  }

  public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
  {
    var http = context.HttpContext;

    if (http.Items.TryGetValue("AuditLog_Processed", out var processed) &&
         processed is bool isProcessed && isProcessed)
    {
      await next();
      return;
    }
    http.Items["AuditLog_Processed"] = true;
    //跳过标记
    if (context.ActionDescriptor.EndpointMetadata
               .OfType<SkipAuditLogAttribute>()
               .Any())
    {
      await next(); return;
    }

    var executed = await next();

    // 如果异常已被其他处理器处理，跳过记录
    if (executed.ExceptionHandled)
    {
      return;
    }

    // var http = context.HttpContext;
    int status = 200; // 默认 200

    if (executed.Exception != null)
    {
      status = 500;
    }
    else if (executed.Result is ObjectResult objectResult)
    {
      status = objectResult.StatusCode ?? 200;
    }
    else if (executed.Result is StatusCodeResult statusCodeResult)
    {
      status = statusCodeResult.StatusCode;
    }

    var requestId = http.TraceIdentifier;
    Console.WriteLine($"请求 ID: {requestId}, 路径: {http.Request.Path}");

    // 构造日志，仅用现有列
    var log = new OperationLog
    {
      UserId = int.TryParse(http.User.FindFirst(ClaimTypes.NameIdentifier)?.Value, out var uid) ? uid : null,
      Action = $"{context.RouteData.Values["controller"]}.{context.RouteData.Values["action"]}".ToLower(),
      Resource = context.RouteData.Values["controller"]?.ToString(),
      ResourceId = GetResourceId(executed),
      IpAddress = http.Connection.RemoteIpAddress?.ToString(),
      UserAgent = http.Request.Headers["User-Agent"].ToString(),
      ErrorMessage = executed.Exception?.Message ?? "",
      HttpStatus = status,
      CreatedAt = DateTime.UtcNow
    };

    if (executed.Exception != null)
    {
      Console.WriteLine($"异常信息: {executed.Exception.Message}");
      Console.WriteLine($"堆栈跟踪: {executed.Exception.StackTrace}");
    }

    Console.WriteLine($"Result Type: {executed.Result?.GetType().Name}");
    Console.WriteLine($"Status Code: {status}");
    Console.WriteLine($"UserId={log.UserId}, HttpStatus={log.HttpStatus}, IsSuccess={log.HttpStatus < 400}");
    try
    {
      await _uow.OperationLogRepository.AddAsync(log);
      var affectedRows = await _uow.SaveChangesAsync();
      Console.WriteLine($"影响行数: {affectedRows}");
    }
    catch (Exception ex)
    {
      Console.WriteLine($"保存日志失败: {ex.Message}");
      throw; // 重新抛出以观察全局异常处理
    }


  }

  private static int? GetResourceId(ActionExecutedContext ctx)
  {
    // 优先从路由参数里拿 id
    if (ctx.Result is ObjectResult { Value: not null } or &&
        ctx.RouteData.Values.TryGetValue("id", out var rid) && int.TryParse(rid?.ToString(), out var id))
      return id;
    return null;
  }

  private static string GetClientIpAddress(HttpContext context)
  {
    // 首先检查代理头（如果通过反向代理）
    var forwardedFor = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
    if (!string.IsNullOrEmpty(forwardedFor))
    {
      // X-Forwarded-For 可能包含多个IP，取第一个
      var ip = forwardedFor.Split(',')[0].Trim();
      if (!string.IsNullOrEmpty(ip))
        return ip;
    }

    // 检查 X-Real-IP 头
    var realIp = context.Request.Headers["X-Real-IP"].FirstOrDefault();
    if (!string.IsNullOrEmpty(realIp))
      return realIp;

    // 获取远程IP地址
    var remoteIp = context.Connection.RemoteIpAddress;
    if (remoteIp != null)
    {
      // 如果是IPv6的本地环回地址，转换为IPv4
      if (remoteIp.ToString() == "::1")
        return "127.0.0.1";

      // 如果是IPv6地址，但不是本地环回，保持原样
      return remoteIp.ToString();
    }

    return "Unknown";
  }
}